package com.cib.process.chat.service.parser;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cib.process.bean.*;
import com.cib.process.chat.bean.QueryResult;
import com.cib.process.chat.bean.WebhookRequest;
import com.cib.process.chat.core.handler.ActionHandler;
import com.cib.process.chat.core.handler.ActionHandlerFactory;
import com.cib.process.chat.service.ServiceResultParser;
import com.cib.process.chat.service.SmsService;
import com.cib.process.constant.CommChatConstants;
import com.cib.process.util.LoggerHelper;
import com.cib.process.util.RedisKey;
import com.fasterxml.jackson.databind.node.IntNode;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class QueryResultParser implements ServiceResultParser<NGDQueryResult> {
    @Autowired
    private ActionHandlerFactory actionHandlerFactory;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private SmsService smsService;


    @Value("#{'${ngd.filter.suggestAnswer}'.split(',')}")
    private List<String> suggestAnswerList;

    //zhangh:异常码
@Value("#{'${webhook.exceptionCode}")
    private String exceptionCode;

    @Value("#{'${webhook.keymenu}")
    private String keymenu;
    //使用线程池对象
    ExecutorService executorService=Executors.newFixedThreadPool(10);


    private static final String SMS="@SMS@";
    //信用卡
    private static final String C="@CREADIT@";
    //借记卡
    private static final String D="@DEBIT@";
    private static final String E="@CHECK_PWD@";


   /* @Value("#{'${mediumTTS}'.split(',')}")
    private List<String> mediumlist;*/

    @Override
    public ServiceResult parseResult(NGDQueryResult queryResult, String sessionId, String userId) {
        if (queryResult==null){
            LoggerHelper.err(this.getClass(),"[sessionId:{}] [userId:{}] ngd query empty",sessionId,userId);
            return ServiceResult.buildFailedResult(IvrReturnCode.QUERY_SERV_REQ_ERROR);
        }else if (queryResult.getCode()!=200){
            LoggerHelper.err(this.getClass(),"[sessionId:{}] [userId:{}] ndg query error {} {}",sessionId,userId,queryResult.getCode(),queryResult.getMsg());
            return ServiceResult.buildFailedResult(IvrReturnCode.QUERY_SERV_REQ_ERROR);
        }else{
            //获取ngd返回的数据
            NGDQueryResult.NGDQueryData queryData = queryResult.getData();
            //提取数据
            QueryResult queryResult_1=parseData(queryData,userId);
            //通过不同指令选择器处理，并返回结果
            String action = queryResult_1.getAction();
            final ActionHandler actionHandler=handleAction(action);
            return actionHandler.execute(queryResult_1);


        }


    }

    private ActionHandler handleAction(String action) {
        return this.actionHandlerFactory.chooseActionHandler(action);
    }

    private QueryResult parseData(NGDQueryResult.NGDQueryData queryData, String userId) {
        QueryResult queryResult = new QueryResult();
        queryResult.setSessionId(queryData.getSessionId());
        queryResult.setQueryId(queryData.getQueryId());
        //会话模式
        String source = queryData.getSource();
        LoggerHelper.info(this.getClass(),"[sessionid:{}] [queryId:{}] ngd current source:{}",queryData.getSessionId(),queryData.getQueryId(),source);
        //如果source为任务式对话，取意图Id,存入 redis
        if ("task_based".equals(source)){
            Map<String, Object> answers = queryData.getAnswers();
            /**
             * 当source为task_based时
                 * dialogs               List 触发会话树节点详情
                 * context               Map 会话上下文信息，(兼容旧版本，保留)
                 * collectInfo           Map 外呼信息收集
                 * intent                String 意图名称
                 * intentMap             Map 意图详情
                 * entity                Map 实体详情
                 * lastNodeId            String 最近一次触发的会话树节点id
                 * lastEnterTopNodeName  String 上个场景名
                 * enterTopNodeIndex     int 进入场景次数
                 * enterTopNodeName      String 场景名
             */
            getIntent(queryResult,answers);
        }
        //回复文本
        String suggestAnswer = queryData.getSuggestAnswer();
        if (StringUtils.isNotBlank(suggestAnswer)){  //不为null取回复话术
            LoggerHelper.info(this.getClass(),"[sessionId:{}] [queryId:{}] ngd current suggestAnswer",queryData.getSessionId(),queryData.getQueryId(),suggestAnswer);
           //获取指令， 如果不是@开头，则表示是TTS指令
           String action= actionExtract(suggestAnswer);
           queryResult.setAction(action);
           
           //添加发送短信功能
            if (suggestAnswer.contains(SMS)){   //如果回复话术中包含发短信标识
                String sub_content = suggestAnswer.substring(suggestAnswer.indexOf(SMS), suggestAnswer.lastIndexOf(SMS));
                String sms_content = sub_content.replace(SMS, "");

                //将短信内容从话术中去掉
                suggestAnswer = suggestAnswer.replace(sms_content, "");
                //封装webhook对象
                WebhookRequest request=new WebhookRequest();
                request.setAction("sendRemind");
                request.setSessionId(queryData.getSessionId());
                request.setQueryId(queryData.getQueryId());
                Map<String,Object> context=new HashMap<>();
                context.put("userId",userId);
                context.put("cellphone",userId);
                context.put("SMSCntnt",sms_content);
                LoggerHelper.info(this.getClass(),"[sessionId:{}] [queryId:{}] [userId:{}] send sms content:{}",queryData.getSessionId(),queryData.getQueryId(),userId,sms_content);
                request.setContext(context);

                //
                executorService.execute(()->{
                    String s = smsService.sendSms(request);
                    LoggerHelper.info(this.getClass(),"发送短信：{}",s);
                });
            }
            Actions actions = Actions.instanceOf(action);
            switch (actions){
                case PWD:
                    queryResult.setPwdType(encryTypeExtract(suggestAnswer));
                    queryResult.setCheckPwd(checkEasyPwd(suggestAnswer));
                    //提取业务数据
                    businessDataExtract(queryResult,queryData);
                    break;
                case CUST_SVC:
                    String intentId=redisTemplate.opsForValue().get(queryResult.getSessionId()+":"+RedisKey.INTENT);
                    queryResult.setIntentid(intentId);
                    businessDataExtract(queryResult,queryData);
                    break;
            }

            //exceptionCode为@stop@,在配置文件中加上
            if (suggestAnswer.contains(exceptionCode)){
                //得到@stop@的索引号
                int i = suggestAnswer.indexOf(keymenu);
                int j = suggestAnswer.indexOf(exceptionCode);
                //截取@1001@和@stop之间的内容
                String substring = suggestAnswer.substring(i, j);
                queryResult.setSuggestAnswer(substring);
            }else{
                //不包含异常码时仍然走之前的逻辑
                queryResult.setSuggestAnswer(suggestAnswerFilter(suggestAnswer.startsWith("@")?suggestAnswer.substring(6):suggestAnswer));
            }

            return queryResult;
        }
        //如果是澄清
        if ("clarify".equals(source)){
            Map<String, Object> clarifyQuestions = queryData.getClarifyQuestions();
            clarify(queryResult,clarifyQuestions);
        }


        return queryResult;
    }

    private void clarify(QueryResult queryResult, Map<String, Object> clarifyQuestions) {
        if (clarifyQuestions!=null&&clarifyQuestions.size()>0){
            Object voice = clarifyQuestions.get("voice");   //回复话术
            Object text = clarifyQuestions.get("text");
            if (voice!=null){
                Map<String,Object> voiceMap=JSON.parseObject(voice.toString(),Map.class);
                Object content = voiceMap.get("content");  //澄清语句

                LoggerHelper.info(this.getClass(),"[sessionId:{}] [queryId:{}] ngd query clarify",queryResult.getSessionId(),queryResult.getQueryId(),content);
                queryResult.setSuggestAnswer(content==null?"":content.toString());
                queryResult.setAction(Actions.TTS.getCode());
            }else {
                //提供静默话术
                queryResult.setSuggestAnswer("您好，我听不到您的声音了");
                queryResult.setAction(Actions.TTS.getCode());
            }
        }
    }

    /**
     * 话术过滤,过滤包含suggestAnswerList中的数据,即删除话术中的其他指令
     * @param s
     * @return
     */
    private String suggestAnswerFilter(String s) {
        String suggestAnswer_1=s;
        if (suggestAnswerList!=null&&suggestAnswerList.size()>0){
            for (String filterStr : suggestAnswerList) {
                String str=filterStr.replace("(","").replace(")","").trim();
                if (s.contains(str) ){
                    suggestAnswer_1=suggestAnswer_1.replace(str,"");
                }
            }
        }
        return suggestAnswer_1;
    }

    /**
     * 业务数据提取，包括卡号，身份证号，验密标签
     * @param queryResult
     * @param queryData
     */
    private void businessDataExtract(QueryResult queryResult, NGDQueryResult.NGDQueryData queryData) {
        String source = queryData.getSource();
        if ("task_based".equals(source)){
           // 上下文信息。与当前的会话session中的上下文进行合并，若存在key冲突，以传入的key为准
            Map<String, Object> context = queryData.getContext();
            if (context!=null){
                Object cardId = context.get("cardId");
                Object custId = context.get("custId");
                //验密标识1
                Object has_pwd = context.get("has_pwd");
                //验密标识2
                Object hasPwdTag = context.get("hasPwdTag");
                Object ywlx = context.get("ywlx");//业务类型
                queryResult.setCreditId(cardId==null?"":cardId.toString());
                queryResult.setId_card(custId==null?"":custId.toString());
                queryResult.setYwlx(ywlx==null?"01":ywlx.toString());
                queryResult.setIsCertifiedCardPwd(CheckType.N);
                if (StringUtils.isNotEmpty(has_pwd.toString())||"YES".equals(hasPwdTag!=null?hasPwdTag.toString():"")){
                    queryResult.setIsCertifiedCardPwd(CheckType.Y);
                }
            }

        }
    }

    /**
     * 简单密码校验
     * @param suggestAnswer
     * @return
     */
    private CheckType checkEasyPwd(String suggestAnswer) {
        if (suggestAnswer.contains(E)){
            return CheckType.Y;
        }
        return CheckType.N;
    }

    /**
     * 提示需要IVR加密的类型
     *  1-信用卡
     *  2-借记卡
     * @param suggestAnswer
     * @return
     */
    private String encryTypeExtract(String suggestAnswer) {
        if (suggestAnswer.contains(C)){
            return "1";
        }else if (suggestAnswer.contains(D)){
            return "2";
        }
        return "";
    }

    /**
     * 提取指令
     * @param suggestAnswer
     * @return
     */
    public String actionExtract(String suggestAnswer) {
        List<String> actions = CommChatConstants.getActions();
        String action="1005";
        //指令会配置在回复话术的最前面

        if (suggestAnswer.startsWith("@")){
            action=suggestAnswer.substring(0,6).replace("@","");
        }else {
            for (String action_1:actions){
                if (suggestAnswer.contains(action_1)){
                    action=action_1.replace("@","");
                    break;
                }

            }
        }
        return action;
    }

    /**
     * 提出意图ID
     * @param queryResult
     * @param answer
     */
    private void getIntent(QueryResult queryResult, Map<String, Object> answer) {
        if (answer!=null){
            Object intent = answer.get("intent");
            if (intent==null){
                Object intentMap = answer.get("intentMap");
                if (intentMap!=null){
                    Map map = JSON.parseObject(intentMap.toString(), Map.class);
                    Object name = map.get("name");
                    queryResult.setIntentid(name==null?"":name.toString());
                }
            }else{
                queryResult.setIntentid(intent.toString());
            }
            if (StringUtils.isNotBlank(queryResult.getIntentid())){
                //将意图设置进redis缓存
                redisTemplate.opsForValue().set(queryResult.getSessionId()+":"+ RedisKey.INTENT,queryResult.getIntentid(),10L, TimeUnit.MINUTES);
            }
        }

    }
}
